﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MeterControl.Services
{
    public class StateContext
    {
        // Client socket.   
        public Socket WorkSocket = null;
        // Size of receive buffer.   
        public const int BufferSize = 1024;
        // Receive buffer.   
        public byte[] buffer = new byte[BufferSize];
        // Received data string.   
        public StringBuilder sb = new StringBuilder(100);
    }
    public class AsynchronousSocketListener
    {
        // Thread signal.   
        public static ManualResetEvent reSetEvent = new ManualResetEvent(false);
        public AsynchronousSocketListener()
        {
        }
        public static void StartListening()
        {
            // Data buffer for incoming data.   
            byte[] bytes = new Byte[1024];
            // Establish the local endpoint for the socket.   
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
            // Create a TCP/IP socket.   
            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            // Bind the socket to the local   
            try
            {
                listener.Bind(localEndPoint);
                listener.Listen(100);
                while (true)
                {
                    // Set the event to nonsignaled state.   
                    reSetEvent.Reset();
                    // Start an asynchronous socket to listen for connections.   
                    Console.WriteLine("Waiting for a connection...");
                    listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
                    // Wait until a connection is made before continuing.   
                    reSetEvent.WaitOne();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            Console.WriteLine("\nPress ENTER to continue...");
            Console.Read();
        }
        public static void AcceptCallback(IAsyncResult ar)
        {
            // Signal the main thread to continue.   
            reSetEvent.Set();
            // Get the socket that handles the client request.   
            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);
            // Create the state object.   
            StateContext state = new StateContext
            {
                WorkSocket = handler
            };
            handler.BeginReceive(state.buffer, 0, StateContext.BufferSize, 0, new AsyncCallback(ReadCallback), state);
        }
        public static void ReadCallback(IAsyncResult ar)
        {
            String content = String.Empty;
            StateContext state = (StateContext)ar.AsyncState;
            Socket handler = state.WorkSocket;
            // Read data from the client socket.   
            int bytesRead = handler.EndReceive(ar);
            if (bytesRead > 0)
            {
                // There might be more data, so store the data received so far.   
                state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, bytesRead));
                // Check for end-of-file tag. If it is not there, read   
                // more data.   
                content = state.sb.ToString();
                if (content.IndexOf("<EOF>") > -1)
                {
                    Console.WriteLine("读取 {0} bytes. \n 数据: {1}", content.Length, content);
                    Send(handler, content);
                }
                else
                {
                    handler.BeginReceive(state.buffer, 0, StateContext.BufferSize, 0, new AsyncCallback(ReadCallback), state);
                }
            }
        }
        private static void Send(Socket handler, string data)
        {
            byte[] byteData = Encoding.ASCII.GetBytes(data);
            handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
        }
        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                Socket handler = (Socket)ar.AsyncState;
                int bytesSent = handler.EndSend(ar);
                Console.WriteLine("发送 {0} bytes.", bytesSent);
                handler.Shutdown(SocketShutdown.Both);
                handler.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        public static int Main1(String[] args)
        {
            StartListening();
            return 0;
        }
    }
}
